<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html dir="ltr" xml:lang="es" xmlns="http://www.w3.org/1999/xhtml" lang="es"><head>

	
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<meta name="keywords" content="Capítulo 4: Soy un artista... ¡No me coartes!,Capítulo 3: ¡Qué aburrido! yo quiero interactuar,Nuestra primera interfaz gráfica con CodeBlocks y wxWidgets,VirtualBox,WxWidgets,Capítulo 5: El lado oscuro (compilando para Windows)">
<link rel="shortcut icon" href="http://doc.ubuntu-es.org/favicon.ico">
<link rel="search" type="application/opensearchdescription+xml" href="http://doc.ubuntu-es.org/opensearch_desc.php" title="doc.ubuntu-es (Español)">
<link title="Creative Commons" type="application/rdf+xml" href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=creativecommons" rel="meta">
<link rel="copyright" href="http://creativecommons.org/licenses/by-sa/3.0/">
		<title>Capítulo 4: Soy un artista... ¡No me coartes! - doc.ubuntu-es</title>
		<style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "/skins/monobook/main.css?42b"; /*]]>*/</style>
		<link rel="stylesheet" type="text/css" media="print" href="Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21_archivos/commonPrint.css">
		<link rel="stylesheet" type="text/css" media="handheld" href="Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21_archivos/handheld.css">
		<!--[if lt IE 5.5000]><style type="text/css">@import "/skins/monobook/IE50Fixes.css?42b";</style><![endif]-->
		<!--[if IE 5.5000]><style type="text/css">@import "/skins/monobook/IE55Fixes.css?42b";</style><![endif]-->
		<!--[if IE 6]><style type="text/css">@import "/skins/monobook/IE60Fixes.css?42b";</style><![endif]-->
		<!--[if IE 7]><style type="text/css">@import "/skins/monobook/IE70Fixes.css?42b";</style><![endif]-->
		<!--[if lt IE 7]><script type="text/javascript" src="/skins/common/IEFixes.js?42b"></script>
		<meta http-equiv="imagetoolbar" content="no" /><![endif]-->
		
		<script type="text/javascript">/*<![CDATA[*/
var skin = "monobook";
var stylepath = "/skins";
var wgArticlePath = "/$1";
var wgScriptPath = "";
var wgServer = "http://doc.ubuntu-es.org";
var wgCanonicalNamespace = "";
var wgCanonicalSpecialPageName = false;
var wgNamespaceNumber = 0;
var wgPageName = "Capítulo_4:_Soy_un_artista..._¡No_me_coartes!";
var wgTitle = "Capítulo 4: Soy un artista... ¡No me coartes!";
var wgArticleId = "1930";
var wgIsArticle = true;
var wgUserName = null;
var wgUserLanguage = "es";
var wgContentLanguage = "es";
var wgBreakFrames = false;
var wgCurRevisionId = "11598";
/*]]>*/</script>
                
		<script type="text/javascript" src="Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21_archivos/wikibits.js"><!-- wikibits js --></script>
		<script type="text/javascript" src="Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21_archivos/index.php"><!-- site js --></script>
		<style type="text/css">/*<![CDATA[*/
@import "/index.php?title=MediaWiki:Common.css&usemsgcache=yes&action=raw&ctype=text/css&smaxage=18000";
@import "/index.php?title=MediaWiki:Monobook.css&usemsgcache=yes&action=raw&ctype=text/css&smaxage=18000";
@import "/index.php?title=-&action=raw&gen=css&maxage=18000";
/*]]>*/</style>
		<!-- Head Scripts -->
		<script type="text/javascript" src="Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21_archivos/ajax.js"></script>
<script src="Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21_archivos/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-3100124-1";
urchinTracker();
</script>
	</head><body class="mediawiki ns-0 ltr page-Capítulo_4_Soy_un_artista_¡No_me_coartes">
	<div id="globalWrapper">
		<div id="column-content">
	<div id="content">
		<a name="top" id="top"></a>
				<h1 class="firstHeading">Capítulo 4: Soy un artista... ¡No me coartes!</h1>
		<div id="bodyContent">
			<h3 id="siteSub">De doc.ubuntu-es</h3>
			<div id="contentSub"></div>
									<div id="jump-to-nav">Saltar a <a href="#column-one">navegación</a>, <a href="#searchInput">búsqueda</a></div>			<!-- start content -->
			<table id="toc" class="toc" summary="Tabla de contenidos"><tbody><tr><td><div id="toctitle"><h2>Tabla de contenidos</h2> <span class="toctoggle">[<a href="javascript:toggleToc()" class="internal" id="togglelink">esconder</a>]</span></div>
<ul>
<li class="toclevel-1"><a href="#Introducci.C3.B3n"><span class="tocnumber">1</span> <span class="toctext">Introducción</span></a></li>
<li class="toclevel-1"><a href="#Creaci.C3.B3n_de_una_wxWindow:"><span class="tocnumber">2</span> <span class="toctext">Creación de una wxWindow:</span></a></li>
<li class="toclevel-1"><a href="#Organizaci.C3.B3n_de_los_elementos_en_la_ventana_.28sizers.29:"><span class="tocnumber">3</span> <span class="toctext">Organización de los elementos en la ventana (sizers):</span></a>
<ul>
<li class="toclevel-2"><a href="#Creaci.C3.B3n_de_algunos_elementos_basura:"><span class="tocnumber">3.1</span> <span class="toctext">Creación de algunos elementos basura:</span></a></li>
<li class="toclevel-2"><a href="#Colocaci.C3.B3n_de_los_elementos."><span class="tocnumber">3.2</span> <span class="toctext">Colocación de los elementos.</span></a></li>
</ul>
</li>
<li class="toclevel-1"><a href="#Pintado_de_la_wxWindow:"><span class="tocnumber">4</span> <span class="toctext">Pintado de la wxWindow:</span></a>
<ul>
<li class="toclevel-2"><a href="#Pintado_directo_.28wxPaintDC.29."><span class="tocnumber">4.1</span> <span class="toctext">Pintado directo (wxPaintDC).</span></a></li>
<li class="toclevel-2"><a href="#Pintado_sobre_un_bitmap_.28wxMemoryDC.29."><span class="tocnumber">4.2</span> <span class="toctext">Pintado sobre un bitmap (wxMemoryDC).</span></a></li>
<li class="toclevel-2"><a href="#Pintado_con_contexto_gr.C3.A1fico."><span class="tocnumber">4.3</span> <span class="toctext">Pintado con contexto gráfico.</span></a></li>
</ul>
</li>
<li class="toclevel-1"><a href="#Conclusi.C3.B3n"><span class="tocnumber">5</span> <span class="toctext">Conclusión</span></a></li>
<li class="toclevel-1"><a href="#Primera_despedida"><span class="tocnumber">6</span> <span class="toctext">Primera despedida</span></a></li>
</ul>
</td></tr></tbody></table><script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "mostrar"; var tocHideText = "esconder"; showTocToggle(); } </script>
<a name="Introducci.C3.B3n"></a><h2><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit&amp;section=1" title="Editar sección: Introducción">editar</a>]</span> <span class="mw-headline"> Introducción </span></h2>
<p>En este capítulo no vamos a introducir nada nuevo, tan sólo vamos a
trabajar con dos elementos un tanto singulares, ambos dedicados a
desarrollarnos como artistas, pues el primero son los sizers, que nos
ayudarán enormemente a organizar nuestras ventanas, y el segundo es
wxWindow, que serán las ventanas donde pintaremos.
</p><p>Parecerá chocante la forma de moverse de wxWidgets en cuanto a
nomenclatura, pues las wxWindow serán para nosotros lo que para el
resto de la humanidad son las Canvas, wxFrame, como ya vimos en
capítulos anteriores, no serán pantallas (para pintar por ejemplo),
sino ventanas de cabecera. El único que mantiene una cierta línea
clásica es wxDialog, que aunque no llegaremos a usarlo, os podeis
imaginar que su uso será del todo análogo.
</p><p>Por tanto presentemos el plan de trabajo para este capítulo:
</p>
<ul><li> Plan de trabajo del capítulo 4:
<ul><li> Creación de una wxWindow: <br>Crearemos nuestra primera ventana para pintar, dentro del propio TopFrame.
</li><li> Organización de los elementos en la ventana (sizers): <br>Usando los sizers colocaremos a nuestro gusto todos los elementos que tenemos.
<ul><li> Creación de algunos elementos basura: <br>Crearemos unos cuantos cuadros de texto y labels para tener mas objetos que poder colocar.
</li><li> Colocación de los elementos.
</li></ul>
</li><li> Pintado de la wxWindow:
<ul><li> Pintado directo (wxPaintDC).
</li><li> Pintado sobre un bitmap (wxMemoryDC).
</li><li> Pintado con contexto gráfico. (de momento queda pendiente)
</li></ul>
</li></ul>
</li></ul>
<p>El último punto es realmente interesante, y una de las más modernas
implementaciones de estas magníficas librerías. No obstante esta
herramienta nos costará algunos disgustos cuando compilemos en Windows,
lo primero porque en Windows tienes que añadir estas librerías
manualmente, y lo segundo porque sufren de una alta inestabilidad.
</p><p>Hecha esta breve introducción, procedamos a trabajar un poco...
</p>
<a name="Creaci.C3.B3n_de_una_wxWindow:"></a><h2><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit&amp;section=2" title="Editar sección: Creación de una wxWindow:">editar</a>]</span> <span class="mw-headline"> Creación de una wxWindow: </span></h2>
<p>Como siempre, con nuestra API bien cerquita, acudimos a ella y
buscamos wxWindow, y nos informamos de todas las posibilidades que
tiene (que son muchas). Para proceder con una wxWindow, al igual que
con una wxFrame, y con un wxDialog, nos crearemos una clase heredada de
wxWindow.
</p><p>Ya introducimos esta idea cuando creamos nuestra wxFrame, y ya
adelantabamos que cuando nos encontráramos con elementos complicados
(una ventana, un dialogo, un canvas, una malla...) debíamos actuar de
esta forma.
</p><p>Bueno, ya que hemos alineado un poco nuestras ideas,
recuperamos nuestro proyecto donde lo dejamos, y creamos dos archivos,
llamados "<b>mycanvas.cpp</b>" y "<b>mycanvas.h</b>", y como siempre los limpiamos.
</p><p>Y declaramos nuestra nueva clase, en "<b>mycanvas.h</b>":
</p>
<pre> class MyCanvas&nbsp;: public wxWindow
 {
 public:
 	MyCanvas(SampleApp * AApp, wxWindow *parent, wxWindowID id, const wxPoint&amp; 
       pos=wxDefaultPosition, const wxSize&amp; size = wxDefaultSize, long style = 0);
 
 	void drawSomething();
     wxMemoryDC dc;
     wxGraphicsContext *gc;
 
 protected: // event handlers (NO virtual)
 	void OnPaint(wxPaintEvent&amp; event);
 	void OnMaximize(wxSizeEvent&amp; event);
 private:
 	wxBitmap m_pixels;
 	SampleApp * App;
 
 	// any class wishing to process wxWidgets events must use this macro
 	DECLARE_EVENT_TABLE()
 };
</pre>
<p>En un acto de previsión, hemos ido añadiendo todo aquello que
creemos que vamos a necesitar, tal vez sería buena idea que buscarais
en el API todos los elementos que hemos añadido.
</p><p>El siguiente punto es crear nuestra clase, en "<b>mycanvas.cpp</b>":
</p>
<pre> #include &lt;wx/wx.h&gt;
 #include &lt;wx/icon.h&gt;
 #include &lt;wx/font.h&gt;
 #include &lt;wx/numdlg.h&gt;
 #include &lt;wx/string.h&gt;
 #include &lt;wx/event.h&gt;
 #include &lt;wx/textctrl.h&gt;
 #include &lt;wx/wfstream.h&gt;
 #include &lt;wx/datstrm.h&gt;
 #include &lt;wx/txtstrm.h&gt;
 #include &lt;wx/access.h&gt;
 #include &lt;wx/window.h&gt;
 #include &lt;wx/treectrl.h&gt;
 #include &lt;wx/spinctrl.h&gt;
 #include &lt;wx/collpane.h&gt;
 #include &lt;wx/stdpaths.h&gt;
 #include &lt;wx/datetime.h&gt;
 #include &lt;wx/graphics.h&gt;
 #include "main.h"
 #include "mycanvas.h"
 
 BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
 	EVT_PAINT(MyCanvas::OnPaint)			//to can paint in window
 	EVT_SIZE(MyCanvas::OnMaximize)			//answer to size changes (p.ej. maximize events)	
 END_EVENT_TABLE()
 
 const int BMPW = 3000;	//auxvars
 const int BMPH = 2000;	//auxvars
 
 MyCanvas::MyCanvas(SampleApp * AApp, wxWindow *parent, wxWindowID id, const wxPoint&amp; 
  pos /*= wxDefaultPosition*/, const wxSize&amp; size /*= wxDefaultSize*/, long style /*= 0*/)
&nbsp;:wxWindow(parent,id,pos,size,style),
 m_pixels(BMPW,BMPH,-1)
 {
     App = AApp;
 }
 
 /***************************************************************/
 /**************	OnMaximize	************************************/
 /************** answer to Size changes	************************/
 /************** Used to resize all elements	********************/
 /***************************************************************/
 void MyCanvas::OnMaximize(wxSizeEvent&amp; WXUNUSED(event))
 {
 }
 
 /***************************************************************/
 /**************	OnPaint	****************************************/
 /************** answer to paint events *************************/
 /************** Prepares the window to paint it ****************/
 /***************************************************************/
 void MyCanvas::OnPaint(wxPaintEvent&amp; WXUNUSED(event))
 {
 }
 
 /***************************************************************/
 /**************	drawSomething	********************************/
 /************** Paint the canvas	****************************/
 /***************************************************************/
 void MyCanvas::drawSomething()
 {
 }
</pre>
<p>Paremos un segundo a explicar a que viene cada cosa.
</p>
<ol><li> De repente añado un montón de librerías, que ni siquiera nos
son necesarias... Esas librerías son las típicas que casi seguro tarde
o temprano terminareis por usar, es por eso que las añado.
</li><li> ¿Un sizeevent?... Como maximizamos nuestra TopFrame, es
previsible que el tamaño de esta ventana cambie junto a el, On Maximize
será el encargado de arreglar los posibles desperfectos.
</li><li> ¿Dos constantes?... Efectivamente, si miramos esas líneas de código:
</li></ol>
<pre> (...)
 <b>const int BMPW = 3000;	//auxvars
 const int BMPH = 2000;	//auxvars</b>
 
 MyCanvas::MyCanvas(SampleApp * AApp, wxWindow *parent, wxWindowID id, const wxPoint&amp; 
  pos /*= wxDefaultPosition*/, const wxSize&amp; size /*= wxDefaultSize*/, long style /*= 0*/)
&nbsp;:wxWindow(parent,id,pos,size,style),
 <b>m_pixels(BMPW,BMPH,-1)</b>
 (...)
</pre>
<p>Lo que hacemos es crear un ancho y un alto, y montar con ellos
nuestro bitmap (m_pixels). Ya veremos su utilidad, de momento nos
bastará con saber que estos valores deben ser superiores a la
resolución de pantalla, o por lo menos al tamaño de la ventana.
</p><p>Respecto a las funciones, pues lo mas interesante es que
tenemos un drawSomething(), que será al que llamaremos para pintar, y
que será el que cree el evento para que OnPaint haga el trabajo. Esto
es un primer esbozo, porque pronto veremos como no trabajaremos
exactamente así.
</p><p>Bueno, y ahora solo resta añadirla a topframe, así que empezamos por "<b>topframe.h</b>":
</p>
<pre> (...)
 private:
 	SampleApp * App;
 	<b>MyCanvas * m_drawPanel;</b>
     DECLARE_EVENT_TABLE()
 };
</pre>
<p>Haber incluido esta clase en la cabecera de topframe, nos obliga a
que siempre que se incluya "topframe.h", haya que incluir antes
"mycnavas.h", y por otro lado, "mycanvas.h" requiere de "main.h" antes
de ella. Así, en "<b>main.cpp</b>" debemos añadir lo siguiente:
</p>
<pre> (...)
 #include "main.h"
 <b>#include "mycanvas.h"</b>
 #include "topframe.h"
 (...)
</pre>
<p>Y añadimos y construimos MyCanvas en "<b>topframe.cpp</b>":
</p>
<pre> (...)
 #include "main.h"
 <b>#include "mycanvas.h"</b>
 #include "topframe.h"
 #include "header.h"
 (...)
</pre>
<pre>(...)
 	ProgressBar = new wxGauge(ControlPanel, wxID_ANY, 100, wxPoint(3,3), wxSize(250,32));
 	MyCanvas * drawPanel = new MyCanvas(App,this, wxID_ANY, wxPoint(0,35), wxSize(640 , 480), wxTAB_TRAVERSAL | wxSUNKEN_BORDER);
     m_drawPanel = drawPanel;
 
     //toolbar
(...)
</pre>
<p>Con lo que creamos nuestra ventana en el punto wxPoint(0,35) con un tamaño de wxSize(640 , 480).
</p><p>Compilamos y ejecutamos... ¡Y allí está! ¡nuestra ventana!
</p><p>Pero el aspecto no es precisamente el deseado ¿verdad?, para arreglar esto vamos a recurrir a los sizers.
</p>
<a name="Organizaci.C3.B3n_de_los_elementos_en_la_ventana_.28sizers.29:"></a><h2><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit&amp;section=3" title="Editar sección: Organización de los elementos en la ventana (sizers):">editar</a>]</span> <span class="mw-headline"> Organización de los elementos en la ventana (sizers): </span></h2>
<p>Los sizers son una herramienta indispensable en la programación con
wxWidgets, y se deben tener siempre presentes a la hora de programar.
Nosotros concretamente vamos a usar wxBoxSizer, aunque existen algunas
otras variantes que pueden ser muy interesantes. Pero para poder dar un
poco más de juego, vamos primero a crear algunos elementos basura.
</p>
<a name="Creaci.C3.B3n_de_algunos_elementos_basura:"></a><h3><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit&amp;section=4" title="Editar sección: Creación de algunos elementos basura:">editar</a>]</span> <span class="mw-headline"> Creación de algunos elementos basura: </span></h3>
<p>Propongamos poner, en la parte superior la scrollbar con un título
(una etiqueta), y debajo, en la izquierda una columna de dos cuadros de
texto, precedidos de una label, y en la derecha nuestro recien creado
Canvas...
</p><p>Asi que nos faltan dos etiquetas, y dos cuadros de texto, que
por supuesto, para encontrar información sobre ellos, recurrimos a
nuestra resabiada API, en la que si buscamos <i>label</i>, podemos encontrar, entre otras cosas, la clase <i>wxStaticText</i>, que es exactamente lo que buscabamos.
</p><p>Así que vayamos a <b>topframe.cpp</b>, y creemos nuestras dos nuevas etiquetas al final del constructor:
</p>
<pre>(...)
   toolBar-&gt;AddTool(ID_START, wxBITMAP(start), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
   toolBar-&gt;AddTool(ID_STOP, wxBITMAP(stop), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
	<b>wxStaticText * aLabel = new wxStaticText(&lt;&lt;DatePanel&gt;&gt;, wxID_ANY, _T("This is a wxGauge"),
                              wxPoint(250, 60), wxDefaultSize,
                              wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
   aLabel-&gt;SetForegroundColour( *wxBLACK );
   
	wxStaticText * bLabel = new wxStaticText(&lt;&lt;DatePanel&gt;&gt;, wxID_ANY, _T("This is 2 wxTextCtrl"),
                              wxPoint(250, 60), wxDefaultSize,
                              wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
   bLabel-&gt;SetForegroundColour( *wxBLACK );</b>
   m_running = false;
(...)
</pre>
<p>Conviene destacar que les he dado un punto de creación a ambas (250,
60), pero ya vereis como eso no importa... Y es importante reseñar que
en el <i>window parent</i>, pongo <b>&lt;&lt;DatePanel&gt;&gt;</b>,
esto es porque como aun no hemos creado paneles para introducir estos
elementos, para que si se nos olvida, nos devuelva un error.
</p><p>Ahora volvemos a nuestro API, y buscamos <i>text</i>, encontrando la clase <i>wxTextCtrl</i>, si nos fijamos en su constructor, aparece algo muy interesante, el validador <i>wxValidator</i>
(pinchamos sobre el link para conseguir información), que nos va a
permitir restringir nuestro segundo cuadro de texto a solo números...
</p><p>Asi que añadimos sendos cuadros de texto a nuestra interfaz, nuevamente al final de <b>topframe.cpp</b>:
</p>
<pre>(...)
   bLabel-&gt;SetForegroundColour( *wxBLACK );    
	<b>// validator that only accept number keys
	wxTextValidator OnlyNum = wxTextValidator(wxFILTER_NUMERIC);
   // text box that accepts all
	wxTextCtrl * aText = new wxTextCtrl(&lt;&lt;DatePanel&gt;&gt;, wxID_ANY, _T("Any text"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT);
   // text box that only take numbers
	wxTextCtrl * bText = new wxTextCtrl(&lt;&lt;DatePanel&gt;&gt;, wxID_ANY, _T("1"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT, OnlyNum);</b>
   m_running = false;
(...)
</pre>
<p>Y ya tenemos nuestros elementos, solo debemos colocarlos...
</p>
<a name="Colocaci.C3.B3n_de_los_elementos."></a><h3><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit&amp;section=5" title="Editar sección: Colocación de los elementos.">editar</a>]</span> <span class="mw-headline"> Colocación de los elementos. </span></h3>
<p>Como ya hemos dicho, nuestros cuadros de texto irán en una columna
diferente de nuestra barra de progreso, luego necesitan un panel
distinto, así que creemos un panel para ellos:
</p>
<pre>(...)
   // Panel
	wxPanel * ControlPanel = new wxPanel(this, wxID_ANY, wxPoint(0,0), wxSize(256, 32));
	<b>wxPanel * ControlPanel2 = new wxPanel(this, wxID_ANY, wxPoint(0,0), wxSize(256, 32));</b>
	ProgressBar = new wxGauge(ControlPanel, wxID_ANY, 100, wxPoint(3,3), wxSize(250,32));
(...)
</pre>
<p>Y ahora ya si, ¡comenzemos con los wxSizers!, como siempre, lo primero la documentación, en la que buscamos <i>sizer</i>, y que rapidamente nos muestra, entre otras cosas, <i>wxBoxSizer</i>.
Bien, si leeemos atentamente la documentación, veremos que estos sizers
nos permiten colocar los elementos como si fueran cajas Cuyo alto y
ancho debe coincidir entre ellas (con sus proporciones), y que nos
permite apilarlas horizontal o verticalmente.
</p><p>Bien, empezemos con nuestro panel para la scrollbar, en el que recordemos, primero va <i>aLabel</i>, y debajo <i>ProgressBar</i>, así que editamos <i>aLabel</i> para que este en el mismo panel que <i>ProgressBar</i>:
</p>
<pre>(...)
	wxStaticText * aLabel = new wxStaticText(<b>ControlPanel</b>, wxID_ANY, _T("This is a wxGauge"),
                              wxPoint(250, 60), wxDefaultSize,
                              wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
   aLabel-&gt;SetForegroundColour( *wxBLACK );
(...)
</pre>
<p>Y al final del constructor de <i>topframe</i> creamos un sizer para ellos:
</p>
<pre>(...)
	wxBoxSizer *cpSizer = new wxBoxSizer(wxVERTICAL);
	cpSizer-&gt;Add(aLabel, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
	cpSizer-&gt;Add(ProgressBar, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
	ControlPanel-&gt;SetSizer/*AndFit*/(cpSizer);
(...)
</pre>
<p>Y repetimos para nuestra columna de cuadros de texto, los cuales editamos para que se incluyan en el <i>ControlPanel2</i>:
</p>
<pre>(...)
	wxStaticText * bLabel = new wxStaticText(ControlPanel2, wxID_ANY, _T("This is 2 wxTextCtrl"),
                              wxPoint(250, 60), wxDefaultSize,
                              wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
    bLabel-&gt;SetForegroundColour( *wxBLACK );    
	// validator that only accept number keys
	wxTextValidator OnlyNum = wxTextValidator(wxFILTER_NUMERIC); 
    // text box that accepts all
	wxTextCtrl * aText = new wxTextCtrl(ControlPanel2, wxID_ANY, _T("Any text"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT);
    // text box that only take numbers
	wxTextCtrl * bText = new wxTextCtrl(ControlPanel2, wxID_ANY, _T("1"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT, OnlyNum);
(...)
</pre>
<p>Y creamos el sizer para este panel:
</p>
<pre>(...)
	wxBoxSizer *cpSizer2 = new wxBoxSizer(wxVERTICAL);
	cpSizer2-&gt;Add(bLabel, wxSizerFlags().Proportion(0).Expand().Border(wxALL,4));
	cpSizer2-&gt;Add(aText, wxSizerFlags().Proportion(0).Expand().Border(wxALL,4));
	cpSizer2-&gt;Add(bText, wxSizerFlags().Proportion(0).Expand().Border(wxALL,4));
	ControlPanel2-&gt;SetSizer/*AndFit*/(cpSizer2);
(...)
</pre>
<p>Bien, habíamos propuesto que esta columna de cuadros de texto
estuvíera emparejada a nuestro canvas, de tal foma que creamos un sizer
horizontal (justo a continuación):
</p>
<pre>(...)
	wxBoxSizer *auxSizer = new wxBoxSizer(wxHORIZONTAL);
	auxSizer-&gt;Add(ControlPanel2, wxSizerFlags().Proportion(0).Expand().Border(wxALL,4));
	auxSizer-&gt;Add(drawPanel, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
(...)
</pre>
<p>Y por último, esta pareja debe situarse debajo de la progress bar,
de tal forma que creamos ya nuestro sizer definitivo, con el que
setearemos ya nuestra ventana:
</p>
<pre>(...)
	wxBoxSizer * topSizer = new wxBoxSizer(wxVERTICAL);
	topSizer-&gt;Add(ControlPanel, wxSizerFlags().Proportion(0).Expand());
	topSizer-&gt;Add(auxSizer, wxSizerFlags().Proportion(1).Expand());
	SetSizerAndFit(topSizer);
(...)
</pre>
<p>Es muy importante el tema de las proporciones... Cuando se pone
proporción 0, se ajusta al tamaño del elemento, haciéndose tan pequeño
como pueda, pero cuando se pone proporción 1, el elemento es el que se
ajusta, haciéndose tan grande como pueda, así, si atendemos a nuestros
sizers, yo le he puesto proporción 1 al canvas, primero en el modo
horizontal en <i>auxSizer</i>, y luego en el modo vertical en <i>topSizer</i>.
</p><p>Compilar y ejecutar para ver el aspecto... ¡Exito rotundo!
</p>
<a name="Pintado_de_la_wxWindow:"></a><h2><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit&amp;section=6" title="Editar sección: Pintado de la wxWindow:">editar</a>]</span> <span class="mw-headline"> Pintado de la wxWindow: </span></h2>
<p>Bueno, pues colocados todos los elementos, ya sólo nos queda pintar
en nuestra wxWindow. pongamos que pintamos una linea vertical cada vez
que se actualiza (en el bucle de la progress bar por ejemplo)...
</p>
<a name="Pintado_directo_.28wxPaintDC.29."></a><h3><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit&amp;section=7" title="Editar sección: Pintado directo (wxPaintDC).">editar</a>]</span> <span class="mw-headline"> Pintado directo (wxPaintDC). </span></h3>
<p>Por supuesto, nada más ver el título, hay que tener ya nuestra documentación en las narices con <i>wxPaintDC</i> abierto. Si investigamos un poco, veremos que hay una gran variedad de formas de pintar en el canvas, pero que destacan dos:
</p>
<ul><li> wxPaintDC<br>Es la forma nativa, y tarde o temprano hay que
usarla, ya que es la que nos pinta realmente sobre la pantalla. No
obstante es la forma más primitiva de hacerlo, y tiene el problema de
que se ve como va evolucionando el pintado, de tal forma que si el
pintado requiere un alto número de operaciones, se verá como se va
realizando, con un molesto parpadeo (efecto flicker).
</li></ul>
<ul><li> wxMemoryDC<br>Precisamente para evitar este problema, se usa
esta clase, que basicamente nos permitirá ir pintando sobre un mapa de
bits, y luego pintar este mapa todo de golpe sobre el canvas usando el <i>wxPaintDC</i>.
</li></ul>
<p>Así que efectivamente, la clase que nos ocupa unicamente se encargará de pintar el bitmap, así pues, en el metodo <b>OnPaint</b> de <b>mycanvas.cpp</b> añadimos:
</p>
<pre>(...)
void MyCanvas::OnPaint(wxPaintEvent&amp; WXUNUSED(event))
{
   	wxPaintDC Pdc(this);
	Pdc.DrawBitmap(m_pixels, 0, 0, false);
}
(...)
</pre>
<p>Que efecitamente, cada vez que llamemos a Update() o a Refresh() (o
a ambas si queremos forzar el pintado inmediato), se entrará en este
método en el que <i>Pdc</i> pintará el bitmap <i>m_pixels</i>.
</p>
<a name="Pintado_sobre_un_bitmap_.28wxMemoryDC.29."></a><h3><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit&amp;section=8" title="Editar sección: Pintado sobre un bitmap (wxMemoryDC).">editar</a>]</span> <span class="mw-headline"> Pintado sobre un bitmap (wxMemoryDC). </span></h3>
<p>Este va a ser el que realmente tenga interés, ya que realmente será
el que haga todo el trabajo... En este caso acudiremos al método <b>drawSomething()</b>.
Pero antes necesitamos dos variables contadoras que nos permitan
colocar nuestros palitos horizontal y verticalmente, así que en <b>mycanvas.h</b> añadimos dos contadores:
</p>
<pre>(...)
public:
	MyCanvas(SampleApp * AApp, wxWindow *parent, wxWindowID id, const wxPoint&amp; pos = wxDefaultPosition, const wxSize&amp; size = wxDefaultSize, long  style = 0);
	void drawSomething();
    wxMemoryDC dc;
    wxGraphicsContext *gc;
    int countx, county;
(...)
</pre>
<p>Y en el constructor de mycanvas, en <b>mycanvas.cpp</b>, iniciamos los contadores:
</p>
<pre>MyCanvas::MyCanvas(SampleApp * AApp, wxWindow *parent, wxWindowID id, const wxPoint&amp; pos /*= wxDefaultPosition*/, const wxSize&amp; size /*= wxDefaultSize*/, long style /*= 0*/)
:wxWindow(parent,id,pos,size,style),
m_pixels(BMPW,BMPH,-1)
{
    App = AApp;
    <b>countx = 0;
    county = 0;</b>
}
</pre>
<p>Y ya podemos pasar a pintar, para ello, en este mismo archivo, en el método drawSomething, creamos nuestro pintor:
</p>
<pre>(...)
void MyCanvas::drawSomething()
{
    wxMemoryDC dc;        
}
(...)
</pre>
<p>Y como tenemos la documentación, sabemos que lo primero que debemos
hacer es seleccionar el bitmap y limpiarlo (el fondo por defecto es
blanco, pero se puede cambiar):
</p>
<pre>(...)
void MyCanvas::drawSomething()
{
    wxMemoryDC dc;        
    dc.SelectObject( m_pixels );
    dc.Clear();
}
(...)
</pre>
<p>Bien, y ahora pintamos un palote de 5 unidades de alto. Este palote
se deberá situar en x=countx, y en y=county*5, luego veremos como nos
movemos con countx y county para que hagan los "retornos de carro" al
llegar al final de la ventana.
</p>
<pre>(...)
void MyCanvas::drawSomething()
{
    wxMemoryDC dc;        
    dc.SelectObject( m_pixels );
    dc.Clear();
    dc.SetPen(wxPen(wxColour(0,0,0)));  //black pen
    dc.DrawLine(countx, county*5, countx, county*5 + 5);
}
(...)
</pre>
<p>Ahora gestionemos countx y county. Countx debe incementarse una
unidad cada vez que se llame a drawSomething, y si en algun momento se
supera el borde de la wxWindow, deberá volver a ser cero,
incrementándose en una unidad county:
</p>
<pre>(...)
void MyCanvas::drawSomething()
{
    wxMemoryDC dc;        
    dc.SelectObject( m_pixels );
    dc.Clear();
    dc.SetPen(wxPen(wxColour(0,0,0)));  //black pen
    dc.DrawLine(countx, county*5, countx, county*5 + 5);
    int sizex,sizey;
    GetSize(&amp;sizex, &amp;sizey);	//take sizes to scale some elements
    countx++;
    if(countx&gt;sizex)
    {
        countx = 0;
        county++;
    }
}
(...)
</pre>
<p>Y por último debemos pedirle a nuestro drawSomething que solicite el pintado:
</p>
<pre>(...)
void MyCanvas::drawSomething()
{
    wxMemoryDC dc;        
    dc.SelectObject( m_pixels );
    dc.Clear();
    dc.SetPen(wxPen(wxColour(0,0,0)));  //black pen
    dc.DrawLine(countx, county*5, countx, county*5 + 5);
    int sizex,sizey;
    GetSize(&amp;sizex, &amp;sizey);	//take sizes to scale some elements
    countx++;
    if(countx&gt;sizex)
    {
        countx = 0;
        county++;
    }
    dc.SelectObject( wxNullBitmap );					//unselect the bitmap
    Refresh(false);							//draw everything
    Update();								//force to paint
}
(...)
</pre>
<p>Y ya está, ahora sólo hay que pedirle al programa que use este método, y para ello vamos a <b>topframe.cpp</b>, y editamos:
</p>
<pre>void TopFrame::OnStart(wxCommandEvent&amp; WXUNUSED(event))
{
    int i;
    bool token_true;
    m_running = true;
    while(m_running)
    {
        for(i=1;i&lt;=100;i++)
        {
            ProgressBar-&gt;SetValue(i);
            while((TopFrame *) App-&gt;Pending())
            {
                token_true=(TopFrame *) App-&gt;Dispatch();
            }
            <b>m_drawPanel-&gt;drawSomething();</b>
        }
        for(i=99;i&gt;=2;i--)
        {
            ProgressBar-&gt;SetValue(i);
            while((TopFrame *) App-&gt;Pending())
            {
                token_true=(TopFrame *) App-&gt;Dispatch();
            }
            <b>m_drawPanel-&gt;drawSomething();</b>
        }
    }
}
</pre>
<p>Compilamos, ejecutamos y damos a <b>start</b>. ¡Esto ya si que empieza a ser un programa!
</p>
<a name="Pintado_con_contexto_gr.C3.A1fico."></a><h3><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit&amp;section=9" title="Editar sección: Pintado con contexto gráfico.">editar</a>]</span> <span class="mw-headline"> Pintado con contexto gráfico. </span></h3>
<p>Aún queda un punto importante a la hora de pintar, y es el pintado
con contexto grafico. No obstante, esta tecnica es algho mas complicada
y larga de explicar, así que sólo haré (al menos de momento) unas
breves reseñas.
</p><p>El pintado con contexto gráfico basicamente lo que permite es
hacer uso de funciones de Cairo en Gnome, o de GDI+ en windows, etc...
Estas funciones son lo que se denominan arte 2D, y consisten
basicamente en uso de texturas, canales alfa (transparencias), y otro
tipo de efecto 2D.
</p><p>El contexto gráfico no esta completamente desarrollado en <a href="http://doc.ubuntu-es.org/WxWidgets" title="WxWidgets">wxWidgets</a>, pero ya es perfectamente usable.
</p><p>Basicamente el modo de uso es cuanto menos poco ordinario, ya
que consiste en anclarlo a nuestro DC (wxPaintDC o wxMemoryDC), de tal
forma que este "hereda" el contexto gráfico.
</p><p>Uno de los grandes problemas de dicho contexto gráfico es que
requiere de algunas librerias un tanto especiales, y hablo de Windows,
que puedes tener o no, luego hay que lo grarselas, y compilar wxWidgets
cambiando algunos headers para que haga uso de ellas.
</p>
<a name="Conclusi.C3.B3n"></a><h2><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit&amp;section=10" title="Editar sección: Conclusión">editar</a>]</span> <span class="mw-headline"> Conclusión </span></h2>
<p>En este capítulo por fin nos hemos logrado un programa decente, y
hemos visto dos puntos fundamentales, los 'sizers', y el 'pintado de
ventanas'.
</p><p>Cierto es que hemos dejado de lado el pintado con contexto
gráfico, pero le hemos hecho una pequeña introducción que tal vez algún
día se complemente con un capítulo dedicado a él.
</p><p>Con la conclusión de este capítulo ya si que no queda ningún
secreto relevante acerca de lo que es la programación con wxWidgets.
Dando un breve repaso, las cosas que nos quedan por aprender son:
</p>
<ul><li> Compilado en Windows
</li><li> Hacer un makefile en Linux (un primer instalador)
</li><li> Hacer un paquete Debian (el instalador que, como usuarios de Ubuntu, más nos interesa)
</li></ul>
<p>Este listado no pretende ser intensivo, pero si extensivo, es decir,
estos son los puntos que seas como sea hay que controlar, pero no
descarto hacer más capítulos con otros puntos.
</p><p>Aún así, en el proximo capítulo volveremos a sentir este
contexto gráfico, pues el primer paso será lograrnos un compilador y
las librerías para Windows, y tendremos muy en cuenta este contexto
gráfico a la hora de compilar las wxWidgets.
</p><p>Pero todo eso será en el próximo capítulo, en el que
efectivamente aprenderemos todo lo necesario para hacer un compilado en
Windows, por ejemplo, haciendo uso de <a href="http://doc.ubuntu-es.org/VirtualBox" title="VirtualBox">VirtualBox</a>.
</p><p>Finalmente nuestros archivos han quedado así:
</p><p><b>topframe.h:</b>
</p>
<pre>class TopFrame&nbsp;: public wxFrame
{
public:
    TopFrame(SampleApp * AApp, wxString Title = _T("Welcome to wxWidgets"));
    void Quit();
    wxGauge * ProgressBar;
    bool m_running;

protected:
    void OnQuit(wxCommandEvent&amp; event);
    void OnQuitX(wxCloseEvent&amp; event);
    void OnStart(wxCommandEvent&amp; event);
    void OnStop(wxCommandEvent&amp; event);
    // any class wishing to process wxWidgets events must use this macro
private:
	SampleApp * App;
	MyCanvas * m_drawPanel;
    DECLARE_EVENT_TABLE()
};
</pre>
<p><b>topframe.cpp:</b>
</p>
<pre>#include &lt;math.h&gt;
#include &lt;stdio.h&gt;
#include &lt;wx/wx.h&gt;
#include &lt;wx/string.h&gt;
#include "start.xpm"
#include "stop.xpm"
#include "main.h"
#include "mycanvas.h"
#include "topframe.h"
#include "header.h"
BEGIN_EVENT_TABLE(TopFrame, wxFrame)
    EVT_MENU(wxID_EXIT,  TopFrame::OnQuit)
    EVT_MENU(ID_START,  TopFrame::OnStart)
    EVT_MENU(ID_STOP,  TopFrame::OnStop)
    EVT_CLOSE(TopFrame::OnQuitX)
END_EVENT_TABLE()
TopFrame::TopFrame(SampleApp * AApp, wxString Title)
: wxFrame(NULL, wxID_ANY, Title)
{
	App = AApp;
	//creamos un menu muy simple
	wxMenu *fileMenu = new wxMenu;
	fileMenu-&gt;Append(wxID_EXIT, _T("&amp;Exit\tAlt-F4"), _T("Termina el programa"));
	wxMenuBar *menuBar = new wxMenuBar();
	menuBar-&gt;Append(fileMenu, _T("&amp;File"));
	SetMenuBar(menuBar);
    // Panel
	wxPanel * ControlPanel = new wxPanel(this, wxID_ANY, wxPoint(0,0), wxSize(256, 32));
	wxPanel * ControlPanel2 = new wxPanel(this, wxID_ANY, wxPoint(0,0), wxSize(256, 32));
	ProgressBar = new wxGauge(ControlPanel, wxID_ANY, 100, wxPoint(3,3), wxSize(250,32));
	MyCanvas * drawPanel = new MyCanvas(App,this, wxID_ANY, wxPoint(0,35), wxSize(640 , 480), wxTAB_TRAVERSAL | wxSUNKEN_BORDER);
    m_drawPanel = drawPanel;
    //toolbar
    wxToolBar *toolBar = CreateToolBar();//nueva toolbar(constructor)
    toolBar-&gt;SetMargins(5, 5);//margenes
    toolBar-&gt;SetToolBitmapSize(wxSize(32, 32));//recoratara las imagenes a 32x32
    toolBar-&gt;AddTool(ID_START, wxBITMAP(start), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
    toolBar-&gt;AddTool(ID_STOP, wxBITMAP(stop), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
    toolBar-&gt;Realize();
	wxStaticText * aLabel = new wxStaticText(ControlPanel, wxID_ANY, _T("This is a wxGauge"),
                               wxPoint(250, 60), wxDefaultSize,
                               wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
    aLabel-&gt;SetForegroundColour( *wxBLACK );
	wxStaticText * bLabel = new wxStaticText(ControlPanel2, wxID_ANY, _T("This is 2 wxTextCtrl"),
                               wxPoint(250, 60), wxDefaultSize,
                               wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
    bLabel-&gt;SetForegroundColour( *wxBLACK );
	// validator that only accept number keys
	wxTextValidator OnlyNum = wxTextValidator(wxFILTER_NUMERIC);
    // text box that accepts all
	wxTextCtrl * aText = new wxTextCtrl(ControlPanel2, wxID_ANY, _T("Any text"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT);
    // text box that only take numbers
	wxTextCtrl * bText = new wxTextCtrl(ControlPanel2, wxID_ANY, _T("1"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT, OnlyNum);
	wxBoxSizer *cpSizer = new wxBoxSizer(wxVERTICAL);
	cpSizer-&gt;Add(aLabel, wxSizerFlags().Proportion(0).Expand().Border(wxALL,4));
	cpSizer-&gt;Add(ProgressBar, wxSizerFlags().Proportion(0).Expand().Border(wxALL,4));
	ControlPanel-&gt;SetSizer/*AndFit*/(cpSizer);
	wxBoxSizer *cpSizer2 = new wxBoxSizer(wxVERTICAL);
	cpSizer2-&gt;Add(bLabel, wxSizerFlags().Proportion(0).Expand().Border(wxALL,4));
	cpSizer2-&gt;Add(aText, wxSizerFlags().Proportion(0).Expand().Border(wxALL,4));
	cpSizer2-&gt;Add(bText, wxSizerFlags().Proportion(0).Expand().Border(wxALL,4));
	ControlPanel2-&gt;SetSizer/*AndFit*/(cpSizer2);
	wxBoxSizer *auxSizer = new wxBoxSizer(wxHORIZONTAL);
	auxSizer-&gt;Add(ControlPanel2, wxSizerFlags().Proportion(0).Expand().Border(wxALL,4));
	auxSizer-&gt;Add(drawPanel, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
	wxBoxSizer * topSizer = new wxBoxSizer(wxVERTICAL);
	topSizer-&gt;Add(ControlPanel, wxSizerFlags().Proportion(0).Expand());
	topSizer-&gt;Add(auxSizer, wxSizerFlags().Proportion(1).Expand());
	SetSizerAndFit(topSizer);
    m_running = false;
}
void TopFrame::OnQuit(wxCommandEvent&amp; WXUNUSED(event))
{
    Quit();
}
void TopFrame::Quit()
{
    // true is to force the frame to close
    Close(true);
}
void TopFrame::OnQuitX(wxCloseEvent&amp; WXUNUSED(event))
{
    /**************************************/
    /***** | Aqui todas las ordenes | *****/
    /***** |  previas al cerrado    | *****/
    /******V************************V******/
    // Por ejemplo
    // remove( "temporal.tmp" );
    /******A************************A******/
    /***** | Aqui todas las ordenes | *****/
    /***** |  previas al cerrado    | *****/
    /**************************************/
	Destroy();
}
void TopFrame::OnStart(wxCommandEvent&amp; WXUNUSED(event))
{
    int i;
    bool token_true;

    m_running = true;

    while(m_running)
    {
        for(i=1;i&lt;=100;i++)
        {
            ProgressBar-&gt;SetValue(i);
            while((TopFrame *) App-&gt;Pending())
            {
                token_true=(TopFrame *) App-&gt;Dispatch();
            }
            m_drawPanel-&gt;drawSomething();
        }
        for(i=99;i&gt;=2;i--)
        {
            ProgressBar-&gt;SetValue(i);
            while((TopFrame *) App-&gt;Pending())
            {
                token_true=(TopFrame *) App-&gt;Dispatch();
            }
            m_drawPanel-&gt;drawSomething();
        }
    }
}
void TopFrame::OnStop(wxCommandEvent&amp; WXUNUSED(event))
{
    m_running = false;
}
</pre>
<p><b>mycanvas.h</b>
</p>
<pre>class MyCanvas&nbsp;: public wxWindow
{
public:
	MyCanvas(SampleApp * AApp, wxWindow *parent, wxWindowID id, const wxPoint&amp; pos = wxDefaultPosition, const wxSize&amp; size = wxDefaultSize, long style = 0);
	void drawSomething();
    wxMemoryDC dc;
    wxGraphicsContext *gc;
    int countx, county;
protected: // event handlers (NO virtual)
	void OnPaint(wxPaintEvent&amp; event);
	void OnMaximize(wxSizeEvent&amp; event);
private:
	wxBitmap m_pixels;
	SampleApp * App;
	// any class wishing to process wxWidgets events must use this macro
	DECLARE_EVENT_TABLE()
};
</pre>
<p><b>mycanvas.cpp</b>
</p>
<pre>#include &lt;wx/wx.h&gt;
#include &lt;wx/icon.h&gt;
#include &lt;wx/font.h&gt;
#include &lt;wx/numdlg.h&gt;
#include &lt;wx/string.h&gt;
#include &lt;wx/event.h&gt;
#include &lt;wx/textctrl.h&gt;
#include &lt;wx/wfstream.h&gt;
#include &lt;wx/datstrm.h&gt;
#include &lt;wx/txtstrm.h&gt;
#include &lt;wx/access.h&gt;
#include &lt;wx/window.h&gt;
#include &lt;wx/treectrl.h&gt;
#include &lt;wx/spinctrl.h&gt;
#include &lt;wx/collpane.h&gt;
#include &lt;wx/stdpaths.h&gt;
#include &lt;wx/datetime.h&gt;
#include &lt;wx/graphics.h&gt;
#include "main.h"
#include "mycanvas.h"
BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
	EVT_PAINT(MyCanvas::OnPaint)			//to can paint in window
	EVT_SIZE(MyCanvas::OnMaximize)			//answer to size changes (p.ej. maximize events)
END_EVENT_TABLE()
const int BMPW = 3000;	//auxvars
const int BMPH = 2000;	//auxvars
MyCanvas::MyCanvas(SampleApp * AApp, wxWindow *parent, wxWindowID id, const wxPoint&amp; pos /*= wxDefaultPosition*/, const wxSize&amp; size /*= wxDefaultSize*/, long style /*= 0*/)
:wxWindow(parent,id,pos,size,style),
m_pixels(BMPW,BMPH,-1)
{
    App = AApp;
}
/***************************************************************/
/**************	OnMaximize	************************************/
/************** answer to Size changes	************************/
/************** Used to resize all elements	********************/
/***************************************************************/
void MyCanvas::OnMaximize(wxSizeEvent&amp; WXUNUSED(event))
{
}
/***************************************************************/
/**************	OnPaint	****************************************/
/************** answer to paint events *************************/
/************** Prepares the window to paint it ****************/
/***************************************************************/
void MyCanvas::OnPaint(wxPaintEvent&amp; WXUNUSED(event))
{
   	wxPaintDC Pdc(this);
	Pdc.DrawBitmap(m_pixels, 0, 0, false);
}
/***************************************************************/
/**************	drawSomething	********************************/
/************** Paint the canvas	****************************/
/***************************************************************/
void MyCanvas::drawSomething()
{
    wxMemoryDC dc;
    dc.SelectObject( m_pixels );
    dc.Clear();
    dc.SetPen(wxPen(wxColour(0,0,0)));  //black pen
    dc.DrawLine(countx, county*5, countx, county*5 + 5);
    int sizex,sizey;
    GetSize(&amp;sizex, &amp;sizey);	//take sizes to scale some elements
    countx++;
    if(countx&gt;sizex)
    {
        countx = 0;
        county++;
    }
    dc.SelectObject( wxNullBitmap );						//unselect the bitmap
    Refresh(false);											//draw everything
    Update();
}
</pre>
<a name="Primera_despedida"></a><h2><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit&amp;section=11" title="Editar sección: Primera despedida">editar</a>]</span> <span class="mw-headline"> Primera despedida </span></h2>
<p>Quiero hacer una primera despedida, ya que si no pretendes que tus
codigos sirvan en Windows, y tus aplicaciones no las consideras tan
importantes como para construir instaladores, este tutorial se termina
aquí para ti...
</p><p>Espero que hayas disfrutado aprendiendo esta bella, y en el mundo hispano, desconocida herramienta.
</p><p>Los agradecimientos los dejaré para un capítulo a parte.
</p>
<table class="wikitable" align="center" border="1">

<tbody><tr>
<td style="border: 2px solid rgb(139, 103, 58); padding: 5px; text-align: center; background-color: rgb(240, 226, 198); -moz-border-radius-topleft: 8px; -moz-border-radius-topright: 8px; -moz-border-radius-bottomright: 8px; -moz-border-radius-bottomleft: 8px; font-weight: bold;"> <a href="http://doc.ubuntu-es.org/Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar" title="Capítulo 3: ¡Qué aburrido! yo quiero interactuar">Capítulo 3: ¡Qué aburrido! yo quiero interactuar</a>
</td><td style="border: 2px solid rgb(139, 103, 58); padding: 5px; text-align: center; background-color: rgb(240, 226, 198); -moz-border-radius-topleft: 8px; -moz-border-radius-topright: 8px; -moz-border-radius-bottomright: 8px; -moz-border-radius-bottomleft: 8px; font-weight: bold;"> <a href="http://doc.ubuntu-es.org/Nuestra_primera_interfaz_gr%C3%A1fica_con_CodeBlocks_y_wxWidgets" title="Nuestra primera interfaz gráfica con CodeBlocks y wxWidgets">Nuestra primera interfaz gráfica con CodeBlocks y wxWidgets</a>
</td><td style="border: 2px solid rgb(139, 103, 58); padding: 5px; text-align: center; background-color: rgb(240, 226, 198); -moz-border-radius-topleft: 8px; -moz-border-radius-topright: 8px; -moz-border-radius-bottomright: 8px; -moz-border-radius-bottomleft: 8px; font-weight: bold;"> <a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_5:_El_lado_oscuro_%28compilando_para_Windows%29&amp;action=edit" class="new" title="Capítulo 5: El lado oscuro (compilando para Windows)">Capítulo 5: El lado oscuro (compilando para Windows)</a>
</td></tr></tbody></table>

<!-- Saved in parser cache with key doc_u-es:pcache:idhash:1930-0!1!0!!es!2 and timestamp 20100214184743 -->
<div class="printfooter">
Obtenido de "<a href="http://doc.ubuntu-es.org/Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21">http://doc.ubuntu-es.org/Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21</a>"</div>
			<div id="catlinks"><p class="catlinks"><a href="http://doc.ubuntu-es.org/Especial:Categories" title="Especial:Categories">Categoría</a>: <span dir="ltr"><a href="http://doc.ubuntu-es.org/Categor%C3%ADa:Programaci%C3%B3n" title="Categoría:Programación">Programación</a></span></p></div>			<!-- end content -->
			<div class="visualClear"></div>
		</div>
	</div>
		</div>
		<div id="column-one">
	<div id="p-cactions" class="portlet">
		<h5>Vistas</h5>
		<div class="pBody">
			<ul>
						 <li id="ca-nstab-main" class="selected"><a title="Ver el artículo [alt-c]" accesskey="c" href="http://doc.ubuntu-es.org/Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21">Artículo</a></li>
						 <li id="ca-talk" class="new"><a title="Discusión acerca del artículo [alt-t]" accesskey="t" href="http://doc.ubuntu-es.org/index.php?title=Discusi%C3%B3n:Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit">Discusión</a></li>
						 <li id="ca-edit"><a title="Puedes editar esta página. Por favor, usa el botón de previsualización antes de grabar. [alt-e]" accesskey="e" href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=edit">Editar</a></li>
						 <li id="ca-history"><a title="Versiones anteriores de esta página y sus autores [alt-h]" accesskey="h" href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;action=history">Historial</a></li>
				</ul>
		</div>
	</div>
	<div class="portlet" id="p-personal">
		<h5>Herramientas personales</h5>
		<div class="pBody">
			<ul>
				<li id="pt-login"><a title="Te animamos a registrarte, aunque no es obligatorio [alt-o]" accesskey="o" href="http://doc.ubuntu-es.org/index.php?title=Especial:Userlogin&amp;returnto=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21">Registrarse/Entrar</a></li>
			</ul>
		</div>
	</div>
	<div title="Portada" class="portlet" id="p-logo">
		<a style="background-image: url(/skins/common/images/wiki.png);" href="http://doc.ubuntu-es.org/Documentaci%C3%B3n" title="Documentación"></a>
	</div>
	<script type="text/javascript"> if (window.isMSIE55) fixalpha(); </script>
		<div class="portlet" id="p-navigation">
		<h5>Navegación</h5>
		<div class="pBody">
			<ul>
				<li id="n-mainpage"><a title="Visitar la Portada [alt-z]" accesskey="z" href="http://doc.ubuntu-es.org/Documentaci%C3%B3n">Documentación</a></li>
				<li title="Acerca del proyecto, qué puedes hacer, dónde encontrar información" id="n-portal"><a href="http://doc.ubuntu-es.org/doc.ubuntu-es:Portal_de_la_comunidad">Portal de la comunidad</a></li>
				<li title="Información de contexto sobre acontecimientos actuales" id="n-currentevents"><a href="http://doc.ubuntu-es.org/Proyectos">Proyectos</a></li>
				<li id="n-recentchanges"><a title="La lista de cambios recientes en el wiki [alt-r]" accesskey="r" href="http://doc.ubuntu-es.org/Especial:Recentchanges">Cambios recientes</a></li>
				<li id="n-randompage"><a title="Cargar una página aleatoriamente [alt-x]" accesskey="x" href="http://doc.ubuntu-es.org/Especial:Random">Página aleatoria</a></li>
				<li title="El lugar para aprender" id="n-help"><a href="http://doc.ubuntu-es.org/doc.ubuntu-es:Ayuda">Ayuda</a></li>
				<li title="Respáldanos" id="n-sitesupport"><a href="http://doc.ubuntu-es.org/doc.ubuntu-es:Tareas">Tareas</a></li>
			</ul>
		</div>
	</div>
		<div id="p-search" class="portlet">
		<h5><label for="searchInput">Buscar</label></h5>
		<div id="searchBody" class="pBody">
			<form action="/Especial:Search" id="searchform"><div>
				<input id="searchInput" name="search" accesskey="f" type="text">
				<input name="go" class="searchButton" id="searchGoButton" value="Ir" type="submit">&nbsp;
				<input name="fulltext" class="searchButton" id="mw-searchButton" value="Buscar" type="submit">
			</div></form>
		</div>
	</div>
	<div class="portlet" id="p-tb">
		<h5>Herramientas</h5>
		<div class="pBody">
			<ul>
				<li id="t-whatlinkshere"><a title="Lista de todas las páginas del wiki que enlazan con ésta [alt-j]" accesskey="j" href="http://doc.ubuntu-es.org/Especial:Whatlinkshere/Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21">Lo que enlaza aquí</a></li>
				<li id="t-recentchangeslinked"><a title="Cambios recientes en las páginas que enlazan con esta otra [alt-k]" accesskey="k" href="http://doc.ubuntu-es.org/Especial:Recentchangeslinked/Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21">Seguimiento de enlaces</a></li>
<li id="t-upload"><a title="Subir imágenes o archivos multimedia [alt-u]" accesskey="u" href="http://doc.ubuntu-es.org/Especial:Upload">Subir archivo</a></li>
<li id="t-specialpages"><a title="Lista de todas las páginas especiales [alt-q]" accesskey="q" href="http://doc.ubuntu-es.org/Especial:Specialpages">Páginas especiales</a></li>
				<li id="t-print"><a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;printable=yes">Versión para imprimir</a></li>				<li id="t-permalink"><a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21&amp;oldid=11598">Enlace permanente</a></li>			</ul>
		</div>
	</div>
		</div><!-- end of the left (by default at least) column -->
			<div class="visualClear"></div>
			<div id="footer">
				<div id="f-poweredbyico"><a href="http://www.mediawiki.org/"><img src="Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21_archivos/poweredby_mediawiki_88x31.png" alt="Powered by MediaWiki"></a></div>
				<div id="f-copyrightico"><a href="http://creativecommons.org/licenses/by-sa/3.0/"><img src="Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21_archivos/88x31.png" alt="Atribución-Licenciar Igual 3.0"></a></div>
			<ul id="f-list">
				<li id="lastmod"> Esta página fue modificada por última vez el 19:47, 16 dic 2008.</li>
				<li id="viewcount">Esta página ha sido visitada 1.691 veces.</li>
				<li id="copyright">El contenido está disponible bajo los términos de la <i><a href="http://creativecommons.org/licenses/by-sa/3.0/" class="external " title="http://creativecommons.org/licenses/by-sa/3.0/" rel="nofollow">Atribución-Licenciar Igual 3.0</a></i></li>
				<li id="privacy"><a href="http://doc.ubuntu-es.org/doc.ubuntu-es:Pol%C3%ADtica_de_protecci%C3%B3n_de_datos" title="doc.ubuntu-es:Política de protección de datos">Política de protección de datos</a></li>
				<li id="about"><a href="http://doc.ubuntu-es.org/doc.ubuntu-es:Acerca_de" title="doc.ubuntu-es:Acerca de">Acerca de doc.ubuntu-es</a></li>
				<li id="disclaimer"><a href="http://doc.ubuntu-es.org/doc.ubuntu-es:Limitaci%C3%B3n_general_de_responsabilidad" title="doc.ubuntu-es:Limitación general de responsabilidad">Aviso legal</a></li>
			</ul>
		</div>
		
	
		<script type="text/javascript">if (window.runOnloadHook) runOnloadHook();</script>
</div>
<!-- Served by vaca in 0.369 secs. --></body></html>